home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 41 / Amiga Format CD41 (1999-06)(Future Publishing)(GB)[!][issue 1999-07].iso / -seriously_amiga- / programming / other / scm / init5d0.scm < prev    next >
Text File  |  1999-04-19  |  34KB  |  1,056 lines

  1. ;; Copyright (C) 1991-1999 Free Software Foundation, Inc.
  2. ;;
  3. ;; This program is free software; you can redistribute it and/or modify
  4. ;; it under the terms of the GNU General Public License as published by
  5. ;; the Free Software Foundation; either version 2, or (at your option)
  6. ;; any later version.
  7. ;;
  8. ;; This program is distributed in the hope that it will be useful,
  9. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  11. ;; GNU General Public License for more details.
  12. ;;
  13. ;; You should have received a copy of the GNU General Public License
  14. ;; along with this software; see the file COPYING.  If not, write to
  15. ;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  16. ;;
  17. ;; As a special exception, the Free Software Foundation gives permission
  18. ;; for additional uses of the text contained in its release of GUILE.
  19. ;;
  20. ;; The exception is that, if you link the GUILE library with other files
  21. ;; to produce an executable, this does not by itself cause the
  22. ;; resulting executable to be covered by the GNU General Public License.
  23. ;; Your use of that executable is in no way restricted on account of
  24. ;; linking the GUILE library code into it.
  25. ;;
  26. ;; This exception does not however invalidate any other reasons why
  27. ;; the executable file might be covered by the GNU General Public License.
  28. ;;
  29. ;; This exception applies only to the code released by the
  30. ;; Free Software Foundation under the name GUILE.  If you copy
  31. ;; code from other Free Software Foundation releases into a copy of
  32. ;; GUILE, as the General Public License permits, the exception does
  33. ;; not apply to the code that you add in this way.  To avoid misleading
  34. ;; anyone as to the status of such modified files, you must delete
  35. ;; this exception notice from them.
  36. ;;
  37. ;; If you write modifications of your own for GUILE, it is your choice
  38. ;; whether to permit this exception to apply to your modifications.
  39. ;; If you do not wish that, delete this exception notice.
  40.  
  41. ;;;; "Init.scm", Scheme initialization code for SCM.
  42. ;;; Author: Aubrey Jaffer.
  43.  
  44. (define (scheme-implementation-type) 'SCM)
  45. (define (scheme-implementation-version) "5d0")
  46. (define (scheme-implementation-home-page)
  47.   "http://swissnet.ai.mit.edu/~jaffer/SCM.html")
  48.  
  49. (define vicinity:suffix?
  50.   (let ((suffi
  51.      (case (software-type)
  52.        ((AMIGA)                '(#\: #\/))
  53.        ((MACOS THINKC)            '(#\:))
  54.        ((MS-DOS WINDOWS ATARIST OS/2)    '(#\\ #\/))
  55.        ((NOSVE)                '(#\: #\.))
  56.        ((UNIX COHERENT)            '(#\/))
  57.        ((VMS)                '(#\: #\])))))
  58.     (lambda (chr) (memv chr suffi))))
  59.  
  60. (define (pathname->vicinity pathname)
  61.   ;;Go up one level if PATHNAME ends in a vicinity suffix.
  62.   (let loop ((i (- (string-length pathname) 2)))
  63.     (cond ((negative? i) "")
  64.       ((vicinity:suffix? (string-ref pathname i))
  65.        (substring pathname 0 (+ i 1)))
  66.       (else (loop (- i 1))))))
  67.  
  68. ;;; This definition of PROGRAM-VICINITY is equivalent to the one defined
  69. ;;;  SLIB/require.scm.  It is used here to bootstrap
  70. ;;; IMPLEMENTATION-VICINITY and possibly LIBRARY-VICINITY.
  71.  
  72. (define (program-vicinity)
  73.   (if *load-pathname*
  74.       (pathname->vicinity *load-pathname*)
  75.       (error "not loading but called" 'program-vicinity)))
  76.  
  77. (define in-vicinity string-append)
  78.  
  79. ;;; This is the vicinity where this file resides.
  80. (define implementation-vicinity #f)
  81.  
  82. ;;; (library-vicinity) should be defined to be the pathname of the
  83. ;;; directory where files of Scheme library functions reside.
  84.  
  85. ;;; If the environment variable SCHEME_LIBRARY_PATH is undefined, use
  86. ;;; (implementation-vicinity) as (library-vicinity).  "require.scm",
  87. ;;; the first file loaded from (library-vicinity), can redirect it.
  88.  
  89. (define library-vicinity #f)
  90. (define home-vicinity #f)
  91. (define (set-vicinities! init-file)
  92.   (set! implementation-vicinity
  93.     (let ((vic (pathname->vicinity init-file)))
  94.       (lambda () vic)))
  95.   (set! library-vicinity
  96.     (let ((library-path (getenv "SCHEME_LIBRARY_PATH")))
  97.       (if library-path
  98.           (lambda () library-path)
  99.           (lambda ()
  100.         (let ((olv library-vicinity)
  101.               (oload load))
  102.           (dynamic-wind
  103.               (lambda () (set! load identity))
  104.               (lambda ()
  105.             (try-load (in-vicinity (implementation-vicinity)
  106.                            "require.scm")))
  107.               (lambda () (set! load oload)))
  108.           (if (eq? olv library-vicinity)
  109.               (error "Can't find library-vicinity"))
  110.           (library-vicinity))))))
  111.   (set! home-vicinity
  112.     (let ((home (getenv "HOME")))
  113.       (and home
  114.            (case (software-type)
  115.          ((UNIX COHERENT MS-DOS) ;V7 unix has a / on HOME
  116.           (if (not
  117.                (char=? #\/
  118.                    (string-ref home (+ -1 (string-length home)))))
  119.               (set! home (string-append home "/"))))))
  120.       (lambda () home))))
  121. (set-vicinities! *load-pathname*)
  122.  
  123. ;;; Here for backward compatability
  124. (define scheme-file-suffix
  125.   (case (software-type)
  126.     ((NOSVE) (lambda () "_scm"))
  127.     (else (lambda () ".scm"))))
  128.  
  129. (set! *features*
  130.       (append '(getenv tmpnam abort transcript with-file
  131.         ieee-p1178 rev4-report rev4-optional-procedures
  132.         hash object-hash delay dynamic-wind fluid-let
  133.         multiarg-apply multiarg/and- logical defmacro
  134.         string-port source current-time)
  135.           *features*))
  136.  
  137. (define (exec-self)
  138.   (require 'i/o-extensions)
  139.   (execv (execpath) (if *script*
  140.             (cons (car (program-arguments))
  141.                   (cons "\\"
  142.                     (member *script* (program-arguments))))
  143.             (program-arguments))))
  144.  
  145. (define (display-file file)
  146.   (call-with-input-file file
  147.     (lambda (inport)
  148.       (do ((c (read-char inport) (read-char inport)))
  149.       ((eof-object? c))
  150.     (write-char c)))))
  151. (define (terms)
  152.   (display-file (in-vicinity (implementation-vicinity) "COPYING")))
  153.  
  154. ;; Array syntax:
  155. ;; n is a decimal number, which may be elided for a default value of 1. 
  156. ;; #nA\( ... ) character array
  157. ;; #nAt( ... ) boolean array
  158. ;; #nAe[sfdl]( ... ) exact number array
  159. ;; #nAu[sfdl]( ... ) positive exact number array
  160. ;; #nAi[sfdl]( ... ) inexact real number array
  161. ;; #nAic[sfdl]( ... ) inexact complex number array
  162.  
  163. (define (read:array rank port)
  164.   (let ((prot
  165.      (case (char-downcase (peek-char port))
  166.        ((#\\) (read-char port) #\a)
  167.        ((#\t) (read-char port) #t)
  168.        ((#\e)
  169.         (read-char port)
  170.         (case (char-downcase (peek-char port))
  171.           ((#\s) (read-char port) 'exact-short)
  172.           ((#\f #\d #\l) (read-char port) -2)
  173.           (else -2)))
  174.        ((#\u)
  175.         (read-char port)
  176.         (case (char-downcase (peek-char port))
  177.           ((#\s #\f #\d #\l) (read-char port) 2)
  178.           (else 2)))
  179.        ((#\i)
  180.         (read-char port)
  181.         (case (char-downcase (peek-char port))
  182.           ((#\c)
  183.            (read-char port)
  184.            (case (char-downcase (peek-char port))
  185.          ((#\s #\f #\d #\l) (read-char port)))
  186.            0+1.0i)
  187.           ((#\s #\f) (read-char port) 1.0)
  188.           ((#\d #\l) (read-char port) 1/3)
  189.           (else 1/3)))
  190.        (else #f))))
  191.     (list->uniform-array rank prot (read port))))
  192.  
  193. (define (read:sharp c port)
  194.   (define (barf c)
  195.     (error "unknown # object" c))
  196.   (define chr0 (char->integer #\0))
  197.   (define (feature? exp)
  198.     (cond ((symbol? exp)
  199.        (or (memq exp *features*) (eq? exp (software-type))))
  200.       ((and (pair? exp) (list? exp))
  201.        (case (car exp)
  202.          ((not) (not (feature? (cadr exp))))
  203.          ((or) (if (null? (cdr exp)) #f
  204.                (or (feature? (cadr exp))
  205.                (feature? (cons 'or (cddr exp))))))
  206.          ((and) (if (null? (cdr exp)) #t
  207.             (and (feature? (cadr exp))
  208.                  (feature? (cons 'and (cddr exp))))))
  209.          (else (error "read:sharp+ invalid expression " exp))))))
  210.   (case c
  211.     ((#\') (read port))
  212.     ((#\.) (eval (read port)))
  213.     ((#\+) (if (feature? (read port))
  214.            (read port)
  215.            (begin (read port) (if #f #f))))
  216.     ((#\-) (if (not (feature? (read port)))
  217.            (read port)
  218.            (begin (read port) (if #f #f))))
  219.     ((#\a #\A) (read:array 1 port))
  220.     ((#\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7 #\8 #\9)
  221.      (let loop ((arg (- (char->integer c) chr0)))
  222.        (let ((c (peek-char port)))
  223.      (cond ((char-numeric? c)
  224.         (loop (+ (* 10 arg)
  225.              (- (char->integer (read-char port)) chr0))))
  226.            ((memv c '(#\a #\A))
  227.         (read-char port)
  228.         (read:array arg port))
  229.            (else
  230.         (warn "obsolete array read syntax")
  231.         (read:array arg port))))))
  232.     ((#\!) (if (= 1 (line-number))
  233.            (let skip ((metarg? #f))
  234.          (case (read-char port)
  235.            ((#\newline) (if metarg? (skip #t)))
  236.            ((#\\) (skip #t))
  237.            ((#\!) (if (not (and (eqv? #\# (peek-char port))
  238.                     (read-char port)))
  239.                   (skip metarg?)))
  240.            (else (skip metarg?))))
  241.            (barf c)))
  242.     (else (barf c))))
  243.  
  244. ;; We can assume TOK has at least 2 characters.
  245. (define read:sharp-char
  246.   (letrec ((control (lambda (c)
  247.               (and (char? c)
  248.                (if (eqv? c #\?)
  249.                    (integer->char 127)
  250.                    (integer->char
  251.                 (logand 31 (char->integer c)))))))
  252.        (meta (lambda (c)
  253.            (and (char? c)
  254.             (integer->char
  255.              (logior 128 (char->integer c)))))))
  256.     (lambda (tok)
  257.       (case (string-ref tok 0)
  258.     ((#\C #\c)
  259.      (and (char=? #\- (string-ref tok 1))
  260.           (if (= 3 (string-length tok))
  261.           (control (string-ref tok 2))
  262.           (let ((c (read:sharp-char 
  263.                 (substring tok 2 (string-length tok)))))
  264.             (and c (control c))))))
  265.     ((#\^)
  266.      (and (= 2 (string-length tok))
  267.           (control (string-ref tok 1))))
  268.     ((#\M #\m)
  269.      (and (char=? #\- (string-ref tok 1))
  270.           (if (= 3 (string-length tok))
  271.           (meta (string-ref tok 2))
  272.           (let ((c (read:sharp-char
  273.                 (substring tok 2 (string-length tok)))))
  274.             (and c (meta c))))))))))
  275.  
  276.  
  277.  
  278.  
  279. (define type 'type)            ;for /bin/sh hack.
  280. (define : ':)
  281. (define !#(if #f #f))            ;for scsh hack.
  282.  
  283. ;;;; Here are some Revised^2 Scheme functions:
  284. (define 1+
  285.   (let ((+ +))
  286.     (lambda (n) (+ n 1))))
  287. (define -1+
  288.   (let ((+ +))
  289.     (lambda (n) (+ n -1))))
  290. (define 1- -1+)
  291. (define <? <)
  292. (define <=? <=)
  293. (define =? =)
  294. (define >? >)
  295. (define >=? >=)
  296. (define t #t)
  297. (define nil #f)
  298. (define identity
  299.   (if (defined? cr) cr (lambda (x) x)))
  300.  
  301. (if (not (defined? the-macro))
  302.     (define the-macro identity))
  303. (define sequence (the-macro begin))
  304. (define copy-tree @copy-tree)
  305.  
  306. ;;; VMS does something strange when output is sent to both
  307. ;;; CURRENT-OUTPUT-PORT and CURRENT-ERROR-PORT.
  308. (case (software-type) ((VMS) (set-current-error-port (current-output-port))))
  309.  
  310. ;;; OPEN_READ, OPEN_WRITE, and OPEN_BOTH are used to request the proper
  311. ;;; mode to open files in.  MS-DOS does carriage return - newline
  312. ;;; translation if not opened in `b' mode.
  313.  
  314. (define OPEN_READ (case (software-type)
  315.             ((MS-DOS WINDOWS ATARIST) "rb")
  316.             (else "r")))
  317. (define OPEN_WRITE (case (software-type)
  318.              ((MS-DOS WINDOWS ATARIST) "wb")
  319.              (else "w")))
  320. (define OPEN_BOTH (case (software-type)
  321.             ((MS-DOS WINDOWS ATARIST) "r+b")
  322.             (else "r+")))
  323. (define (_IONBF mode) (string-append mode "0"))
  324.  
  325. (define could-not-open #f)
  326.  
  327. (define (open-input-file str)
  328.   (or (open-file str OPEN_READ)
  329.       (and (procedure? could-not-open) (could-not-open) #f)
  330.       (error "OPEN-INPUT-FILE couldn't open file " str)))
  331. (define (open-output-file str)
  332.   (or (open-file str OPEN_WRITE)
  333.       (and (procedure? could-not-open) (could-not-open) #f)
  334.       (error "OPEN-OUTPUT-FILE couldn't open file " str)))
  335. (define (open-io-file str) (open-file str OPEN_BOTH))
  336.  
  337. (define close-input-port close-port)
  338. (define close-output-port close-port)
  339. (define close-io-port close-port)
  340.  
  341. (define (call-with-input-file str proc)
  342.   (let* ((file (open-input-file str))
  343.      (ans (proc file)))
  344.     (close-input-port file)
  345.     ans))
  346.  
  347. (define (call-with-output-file str proc)
  348.   (let* ((file (open-output-file str))
  349.      (ans (proc file)))
  350.     (close-output-port file)
  351.     ans))
  352.  
  353. (define (with-input-from-port port thunk)
  354.   (dynamic-wind (lambda () (set! port (set-current-input-port port)))
  355.         thunk
  356.         (lambda () (set! port (set-current-input-port port)))))
  357.  
  358. (define (with-output-to-port port thunk)
  359.   (dynamic-wind (lambda () (set! port (set-current-output-port port)))
  360.         thunk
  361.         (lambda () (set! port (set-current-output-port port)))))
  362.  
  363. (define (with-error-to-port port thunk)
  364.   (dynamic-wind (lambda () (set! port (set-current-error-port port)))
  365.         thunk
  366.         (lambda () (set! port (set-current-error-port port)))))
  367.  
  368. (define (with-input-from-file file thunk)
  369.   (let* ((nport (open-input-file file))
  370.      (ans (with-input-from-port nport thunk)))
  371.     (close-port nport)
  372.     ans))
  373.  
  374. (define (with-output-to-file file thunk)
  375.   (let* ((nport (open-output-file file))
  376.      (ans (with-output-to-port nport thunk)))
  377.     (close-port nport)
  378.     ans))
  379.  
  380. (define (with-error-to-file file thunk)
  381.   (let* ((nport (open-output-file file))
  382.      (ans (with-error-to-port nport thunk)))
  383.     (close-port nport)
  384.     ans))
  385.  
  386. (define (warn . args)
  387.   (define cep (current-error-port))
  388.   (perror "WARN")
  389.   (errno 0)
  390.   (display "WARN: " cep)
  391.   (if (not (null? args))
  392.       (begin (display (car args) cep)
  393.          (for-each (lambda (x) (display #\  cep) (write x cep))
  394.                (cdr args))))
  395.   (newline cep)
  396.   (force-output cep))
  397.  
  398. (define (error . args)
  399.   (define cep (current-error-port))
  400.   (perror "ERROR")
  401.   (errno 0)
  402.   (display "ERROR: " cep)
  403.   (if (not (null? args))
  404.       (begin (display (car args) cep)
  405.          (for-each (lambda (x) (display #\  cep) (write x cep))
  406.                (cdr args))))
  407.   (newline cep)
  408.   (force-output cep)
  409.   (abort))
  410.  
  411. (define set-errno errno)
  412. (define slib:exit quit)
  413. (define exit quit)
  414.  
  415. (define (print . args)
  416.   (define result #f)
  417.   (for-each (lambda (x) (set! result x) (write x) (display #\ )) args)
  418.   (newline)
  419.   result)
  420. (define (pp . args)
  421.   (for-each pretty-print args)
  422.   (if #f #f))
  423.  
  424. (define (file-exists? str)
  425.   (let ((port (open-file str OPEN_READ)))
  426.     (and port (close-port port) #t)))
  427. (define (file-readable? str)
  428.   (let ((port (open-file str OPEN_READ)))
  429.     (and port
  430.      (char-ready? port)
  431.      (do ((c (read-char port)
  432.          (and (char-ready? port) (read-char port)))
  433.           (i 0 (+ 1 i))
  434.           (l '() (cons c l)))
  435.          ((or (not c) (eof-object? c) (<= 2 i))
  436.           (if (null? l) #f (list->string (reverse l))))))))
  437.  
  438. (define difftime -)
  439. (define offset-time +)
  440.  
  441. (if (not (memq 'ed *features*))
  442.     (begin
  443.       (define (ed . args)
  444.     (system (apply string-append
  445.                (or (getenv "EDITOR") "ed")
  446.                (map (lambda (s) (string-append " " s)) args))))
  447.       (set! *features* (cons 'ed *features*))))
  448.  
  449. (if (not (defined? output-port-width))
  450.     (define (output-port-width . arg) 80))
  451.  
  452. (if (not (defined? output-port-height))
  453.     (define (output-port-height . arg) 24))
  454.  
  455. (if (not (defined? last-pair))
  456.     (define (last-pair l) (if (pair? (cdr l)) (last-pair (cdr l)) l)))
  457.  
  458. (define slib:error error)
  459. (define slib:warn warn)
  460. (define slib:tab #\tab)
  461. (define slib:form-feed #\page)
  462. (define slib:eval eval)
  463.  
  464. ;;; Load.
  465. (define load:indent 0)
  466. (define (load:pre file)
  467.   (define cep (current-error-port))
  468.   (cond ((> (verbose) 1)
  469.      (display
  470.       (string-append ";" (make-string load:indent #\ ) "loading " file)
  471.       cep)
  472.      (set! load:indent (modulo (+ 2 load:indent) 16))
  473.      (newline cep)))
  474.   (force-output cep))
  475.  
  476. (define (load:post filesuf)
  477.   (define cep (current-error-port))
  478.   (errno 0)
  479.   (cond ((> (verbose) 1)
  480.      (set! load:indent (modulo (+ -2 load:indent) 16))
  481.      (display (string-append ";" (make-string load:indent #\ )
  482.                  "done loading " filesuf)
  483.           cep)
  484.      (newline cep)
  485.      (force-output cep))))
  486.  
  487. (define (has-suffix? str suffix)
  488.   (let ((sufl (string-length suffix))
  489.     (sl (string-length str)))
  490.     (and (> sl sufl)
  491.      (string=? (substring str (- sl sufl) sl) suffix))))
  492.  
  493. (define (scm:load file . libs)
  494.   (define filesuf file)
  495.   (define hss (has-suffix? file (scheme-file-suffix)))
  496.   (load:pre file)
  497.   (or (and (defined? link:link) (not hss)
  498.        (or (let ((s2 (file-readable? file)))
  499.          (and s2 (not (equal? "#!" s2)) (apply link:link file libs)))
  500.            (and link:able-suffix
  501.             (let* ((fs (string-append file link:able-suffix))
  502.                (fs2 (file-readable? fs)))
  503.               (and fs2 (apply link:link fs libs) (set! filesuf fs) #t)
  504.               ))))
  505.       (and (null? libs) (try-load file))
  506.       ;;HERE is where the suffix gets specified
  507.       (and (not hss) (errno 0)        ; clean up error from TRY-LOAD above
  508.        (set! filesuf (string-append file (scheme-file-suffix)))
  509.        (try-load filesuf))
  510.       (and (procedure? could-not-open) (could-not-open) #f)
  511.       (begin (set! load:indent 0)
  512.          (error "LOAD couldn't find file " file)))
  513.   (load:post filesuf))
  514. (define load scm:load)
  515. (define slib:load load)
  516.  
  517. (define (scm:load-source file)
  518.   (define sfs (scheme-file-suffix))
  519.   (define filesuf file)
  520.   (load:pre file)
  521.   (or (and (or (try-load file)
  522.            ;;HERE is where the suffix gets specified
  523.            (and (not (has-suffix? file sfs))
  524.             (begin (set! filesuf (string-append file sfs))
  525.                (try-load filesuf)))))
  526.       (and (procedure? could-not-open) (could-not-open) #f)
  527.       (error "LOAD couldn't find file " file))
  528.   (load:post filesuf))
  529. (define slib:load-source scm:load-source)
  530.  
  531. (load (in-vicinity (library-vicinity) "require"))
  532.  
  533. ;;; DO NOT MOVE!  This must be done after "require.scm" is loaded.
  534. (define slib:load-source scm:load-source)
  535. (define slib:load scm:load)
  536.  
  537. (cond ((or (defined? dyn:link)
  538.        (defined? vms:dynamic-link-call)
  539.        (file-exists? (in-vicinity (implementation-vicinity) "hobbit.tms")))
  540.        (load (in-vicinity (implementation-vicinity) "Link"))))
  541.  
  542. (cond ((defined? link:link)
  543.        (define (slib:load-compiled . args)
  544.      (or (apply link:link args)
  545.          (error "Couldn't link files " args)))
  546.        (provide 'compiled)))
  547.  
  548. (define (string-upcase str) (string-upcase! (string-copy str)))
  549. (define (string-downcase str) (string-downcase! (string-copy str)))
  550. (define (string-capitalize str) (string-capitalize! (string-copy str)))
  551. (define string-ci->symbol
  552.   (if (equal? "a" (symbol->string 'a))
  553.       (lambda (str) (string->symbol (string-downcase str)))
  554.       (lambda (str) (string->symbol (string-upcase str)))))
  555.  
  556. (define logical:logand logand)
  557. (define logical:logior logior)
  558. (define logical:logxor logxor)
  559. (define logical:lognot lognot)
  560. (define logical:ash ash)
  561. (define logical:logcount logcount)
  562. (define logical:integer-length integer-length)
  563. (define logical:integer-expt integer-expt)
  564.  
  565. (define logical:bit-field bit-field)
  566. (define bit-extract bit-field)
  567. (define logical:bitwise-if bitwise-if)
  568. (define logical:copy-bit copy-bit)
  569. (define logical:copy-bit-field copy-bit-field)
  570.  
  571. (define (logical:ipow-by-squaring x k acc proc)
  572.   (cond ((zero? k) acc)
  573.     ((= 1 k) (proc acc x))
  574.     (else (logical:ipow-by-squaring (proc x x)
  575.                     (quotient k 2)
  576.                     (if (even? k) acc (proc acc x))
  577.                     proc))))
  578.  
  579. ;defmacro from dorai@cs.rice.edu (heavily hacked by jaffer):
  580. (define *defmacros* '())
  581. (define (defmacro? m) (and (assq m *defmacros*) #t))
  582.  
  583. (define defmacro:transformer
  584.   (lambda (f)
  585.     (procedure->memoizing-macro
  586.       (lambda (exp env)
  587.     (@copy-tree (apply f (cdr exp)))))))
  588.  
  589. (define defmacro
  590.   (let ((defmacro-transformer
  591.       (lambda (name parms . body)
  592.         `(define ,name
  593.            (let ((transformer (lambda ,parms ,@body)))
  594.          (set! *defmacros* (acons ',name transformer *defmacros*))
  595.          (defmacro:transformer transformer))))))
  596.     (set! *defmacros* (acons 'defmacro defmacro-transformer *defmacros*))
  597.     (defmacro:transformer defmacro-transformer)))
  598.  
  599. (define (macroexpand-1 e)
  600.   (if (pair? e) (let ((a (car e)))
  601.           (cond ((symbol? a) (set! a (assq a *defmacros*))
  602.                      (if a (apply (cdr a) (cdr e)) e))
  603.             (else e)))
  604.       e))
  605.  
  606. (define (macroexpand e)
  607.   (if (pair? e) (let ((a (car e)))
  608.           (cond ((symbol? a)
  609.              (set! a (assq a *defmacros*))
  610.              (if a (macroexpand (apply (cdr a) (cdr e))) e))
  611.             (else e)))
  612.       e))
  613.  
  614. (define gentemp
  615.   (let ((*gensym-counter* -1))
  616.     (lambda ()
  617.       (set! *gensym-counter* (+ *gensym-counter* 1))
  618.       (string->symbol
  619.        (string-append "scm:G" (number->string *gensym-counter*))))))
  620.  
  621. (define defmacro:eval slib:eval)
  622. (define defmacro:load load)
  623.  
  624. (define (slib:eval-load <filename> evl)
  625.   (if (not (file-exists? <filename>))
  626.       (set! <filename> (string-append <filename> (scheme-file-suffix))))
  627.   (call-with-input-file <filename>
  628.     (lambda (port)
  629.       (let ((old-load-pathname *load-pathname*))
  630.     (set! *load-pathname* <filename>)
  631.     (do ((o (read port) (read port)))
  632.         ((eof-object? o))
  633.       (evl o))
  634.     (set! *load-pathname* old-load-pathname)))))
  635.  
  636. ;;; Autoloads for SLIB procedures.
  637.  
  638. (define (tracef . args) (require 'trace) (apply tracef args))
  639. (define (trace:tracef . args) (require 'trace) (apply trace:tracef args))
  640. (define (trace-all . args) (require 'debug) (apply trace-all args))
  641. (define (pretty-print . args) (require 'pretty-print)
  642.   (apply pretty-print args))
  643.  
  644. ;;; Macros.
  645.  
  646. ;;; Trace gets redefmacroed when tracef autoloads.
  647. (defmacro trace x
  648.   (if (null? x) '()
  649.       `(begin ,@(map (lambda (x) `(set! ,x (trace:tracef ,x ',x))) x))))
  650. (defmacro break x
  651.   (if (null? x) '()
  652.       `(begin ,@(map (lambda (x) `(set! ,x (break:breakf ,x ',x))) x))))
  653.  
  654. (defmacro defvar (var val)
  655.   `(if (not (defined? ,var)) (define ,var ,val)))
  656. (defmacro defconst (name value)
  657.   (cond ((list? name) `(defconst ,(car name) (lambda ,(cdr name) ,value)))
  658.     (else (cond ((not (slib:eval `(defined? ,name))))
  659.             ((and (symbol? name) (eqv? (slib:eval value)
  660.                            (slib:eval name))))
  661.             (else (slib:error 'trying-to-defconst name
  662.                       'to-different-value value)))
  663.           `(define ,name ,value))))
  664. (defmacro casev (key . clauses)
  665.   `(case ,key
  666.      ,@(map (lambda (clause)
  667.           (if (list? (car clause))
  668.           (cons (apply
  669.              append
  670.              (map (lambda (elt)
  671.                 (case elt
  672.                   ((unquote) '(unquote))
  673.                   ((unquote-splicing) '(unquote-splicing))
  674.                   (else
  675.                    (eval (list 'quasiquote (list elt))))))
  676.                   (car clause)))
  677.             (cdr clause))
  678.           clause))
  679.         clauses)))
  680.  
  681. (defmacro fluid-let (clauses . body)
  682.   (let ((ids (map car clauses))
  683.     (temp (gentemp))
  684.     (swap (gentemp)))
  685.     `(let* ((,temp (list ,@(map cadr clauses)))
  686.         (,swap (lambda () (set! ,temp (set! ,ids ,temp)))))
  687.        (dynamic-wind
  688.        ,swap
  689.        (lambda () ,@body)
  690.        ,swap))))
  691.  
  692. (define print-args
  693.   (procedure->syntax
  694.    (lambda (sexp env)
  695.      (set! env (environment->tree env))
  696.      (let ((frame (and (not (null? env)) (car env))))
  697.        (cond ((not (null? (cdr sexp)))
  698.           (display "In")
  699.           (for-each (lambda (exp) (display #\ ) (display exp)) (cdr sexp))
  700.           (display ": ")))
  701.        (do ((vars (car frame) (cdr vars))
  702.         (vals (cdr frame) (cdr vals)))
  703.        ((not (pair? vars))
  704.         (cond ((not (null? vars))
  705.            (write vars)
  706.            (display " := ")
  707.            (write vals)))
  708.         (newline))
  709.      (write (car vars))
  710.      (display " = ")
  711.      (write (car vals))
  712.      (display "; "))))))
  713.  
  714. (cond
  715.  ((defined? stack-trace)
  716.  
  717.   #+breakpoint-error;; remove line to enable breakpointing on calls to ERROR
  718.   (define (error . args)
  719.     (define cep (current-error-port))
  720.     (perror "ERROR")
  721.     (errno 0)
  722.     (display "ERROR: " cep)
  723.     (if (not (null? args))
  724.     (begin (display (car args) cep)
  725.            (for-each (lambda (x) (display #\  cep) (write x cep))
  726.              (cdr args))))
  727.     (newline cep)
  728.     (cond ((stack-trace) (newline cep)))
  729.     (display " * Breakpoint established: (continue <val>) to return." cep)
  730.     (newline cep) (force-output cep)
  731.     (require 'debug) (apply breakpoint args))
  732.  
  733.   (define (user-interrupt . args)
  734.     (define cep (current-error-port))
  735.     (newline cep) (display "ERROR: user interrupt" cep)
  736.     (newline cep)
  737.     (cond ((stack-trace) (newline cep)))
  738.     (display " * Breakpoint established: (continue <val>) to return." cep)
  739.     (newline cep) (force-output cep)
  740.     (require 'debug) (apply breakpoint args))
  741.   ))
  742.  
  743. ;;; ABS and MAGNITUDE can be the same.
  744. (cond ((and (inexact? (string->number "0.0")) (not (defined? exp)))
  745.        (or (and (defined? usr:lib)
  746.         (usr:lib "m")
  747.         (load (in-vicinity (implementation-vicinity) "Transcen")
  748.               (usr:lib "m")))
  749.        (load (in-vicinity (implementation-vicinity) "Transcen")))
  750.        (set! abs magnitude)))
  751.  
  752. (if (defined? array?)
  753.     (begin
  754.       (define uniform-vector? array?)
  755.       (define make-uniform-vector dimensions->uniform-array)
  756. ;      (define uniform-vector-ref array-ref)
  757.       (define (uniform-vector-set! u i o)
  758.     (uniform-vector-set1! u o i))
  759. ;      (define uniform-vector-fill! array-fill!)
  760. ;      (define uniform-vector-read! uniform-array-read!)
  761. ;      (define uniform-vector-write uniform-array-write)
  762.  
  763.       (define (make-array fill . args)
  764.     (dimensions->uniform-array args () fill))
  765.       (define (make-uniform-array prot . args)
  766.     (dimensions->uniform-array args prot))
  767.       (define (list->array ndim lst)
  768.     (list->uniform-array ndim '() lst))
  769.       (define (list->uniform-vector prot lst)
  770.     (list->uniform-array 1 prot lst))
  771.       (define (array-shape a)
  772.     (let ((dims (array-dimensions a)))
  773.       (if (pair? dims)
  774.           (map (lambda (ind) (if (number? ind) (list 0 (+ -1 ind)) ind))
  775.            dims)
  776.           dims)))))
  777.  
  778. (define (alarm-interrupt) (alarm 0))
  779. (if (defined? setitimer)
  780.     (begin
  781.       (define profile-alarm #f)
  782.       (define (profile-alarm-interrupt) (profile-alarm 0))
  783.       (define virtual-alarm #f)
  784.       (define (virtual-alarm-interrupt) (virtual-alarm 0))
  785.       (define milli-alarm #f)
  786.       (let ((make-alarm
  787.          (lambda (sym)
  788.            (and (setitimer sym 0 0)    ;DJGPP supports only REAL and PROFILE
  789.             (lambda (value . interval)
  790.               (cadr
  791.                (setitimer sym value
  792.                   (if (pair? interval) (car interval) 0))))))))
  793.     (set! profile-alarm (make-alarm 'profile))
  794.     (set! virtual-alarm (make-alarm 'virtual))
  795.     (set! milli-alarm (make-alarm 'real)))))
  796.  
  797. ;;;; Initialize statically linked add-ons
  798. (cond ((defined? scm_init_extensions)
  799.        (scm_init_extensions)
  800.        (set! scm_init_extensions #f)))
  801.  
  802. ;;; Use *argv* instead of (program-arguments), to allow option
  803. ;;; processing to be done on it.  "ScmInit.scm" must
  804. ;;;    (set! *argv* (program-arguments))
  805. ;;; if it wants to alter the arguments which BOOT-TAIL processes.
  806. (define *argv* #f)
  807.  
  808. (if (not (defined? *R4RS-macro*))
  809.     (define *R4RS-macro* #f))
  810. (if (not (defined? *interactive*))
  811.     (define *interactive* #f))
  812.  
  813. (define (boot-tail dumped?)
  814.   (cond ((not *argv*)
  815.      (set! *argv* (program-arguments))
  816.      (cond (dumped?
  817.         (set-vicinities! dumped?)
  818.         (verbose (if (and (isatty? (current-input-port))
  819.                   (isatty? (current-output-port)))
  820.                  (if (<= (length *argv*) 1) 2 1)
  821.                  0))))
  822.      (cond ((provided? 'getopt)
  823.         (set! *optind* 1)
  824.         (set! *optarg* #f)))))
  825.  
  826. ;;; This loads the user's initialization file, or files named in
  827. ;;; program arguments.
  828.   (or (eq? (software-type) 'THINKC)
  829.       (member "-no-init-file" (program-arguments))
  830.       (member "--no-init-file" (program-arguments))
  831.       (try-load (in-vicinity (or (home-vicinity) (user-vicinity))
  832.                  (string-append "ScmInit") (scheme-file-suffix)))
  833.       (errno 0))
  834.  
  835.   (cond
  836.    ((and (> (length *argv*) 1) (char=? #\- (string-ref (cadr *argv*) 0)))
  837.     (require 'getopt)
  838. ;;; (else
  839. ;;;  (define *optind* 1)
  840. ;;;  (define getopt:opt #f)
  841. ;;;  (define (getopt argc argv optstring) #f))
  842.  
  843.     (let* ((simple-opts "muqvbis")
  844.        (arg-opts '("a kbytes" "no-init-file" "-no-init-file"
  845.                   "-version" "-help" "p number"
  846.                   "r feature" "f filename" "l filename"
  847.                   "d filename" "c string" "e string"
  848.                   "o filename"))
  849.        (opts (apply string-append ":" simple-opts
  850.             (map (lambda (o)
  851.                    (string-append (string (string-ref o 0)) ":"))
  852.                  arg-opts)))
  853.        (argc (length *argv*))
  854.        (didsomething #f)
  855.        (moreopts #t)
  856.        (exe-name (symbol->string (scheme-implementation-type)))
  857.        (up-name (apply string (map char-upcase (string->list exe-name)))))
  858.  
  859.       (define (do-thunk thunk)
  860.     (if *interactive*
  861.         (thunk)
  862.         (let ((complete #f))
  863.           (dynamic-wind
  864.            (lambda () #f)
  865.            (lambda ()
  866.          (thunk)
  867.          (set! complete #t))
  868.            (lambda ()
  869.          (if (not complete) (close-port (current-input-port))))))))
  870.  
  871.       (define (do-string-arg)
  872.     (require 'string-port)
  873.     (do-thunk
  874.      (lambda ()
  875.        ((if *R4RS-macro* macro:eval eval)
  876.         (call-with-input-string
  877.          (string-append "(begin " *optarg* ")")
  878.          read))))
  879.     (set! didsomething #t))
  880.  
  881.       (define (do-load file)
  882.     (do-thunk
  883.      (lambda ()
  884.        (cond (*R4RS-macro* (require 'macro) (macro:load file))
  885.          (else (load file)))))
  886.     (set! didsomething #t))
  887.  
  888.       (define (usage preopt opt postopt success?)
  889.     (define cep (if success? (current-output-port) (current-error-port)))
  890.     (define indent (make-string 6 #\ ))
  891.     (define i 3)
  892.     (cond ((char? opt) (set! opt (string opt)))
  893.           ;;((symbol? opt) (set! opt (symbol->string opt)))
  894.           )
  895.     (display (string-append preopt opt postopt) cep)
  896.     (newline cep)
  897.     (display (string-append "Usage: "
  898.                 exe-name
  899.                 " [-a kbytes] [-" simple-opts "]") cep)
  900.     (for-each
  901.      (lambda (o)
  902.        (display (string-append " [-" o "]") cep)
  903.        (set! i (+ 1 i))
  904.        (cond ((zero? (modulo i 4)) (newline cep) (display indent cep))))
  905.      (cdr arg-opts))
  906.     (display " [-- | -s | -] [file] [args...]" cep) (newline cep)
  907.     (if success? (display success? cep) (quit #f)))
  908.  
  909.       ;; -a int => ignore (handled by scm_init_from_argv)
  910.       ;; -c str => (eval str)
  911.       ;; -e str => (eval str)
  912.       ;; -d str => (require 'database-utilities) (open-database str)
  913.       ;; -f str => (load str)
  914.       ;; -l str => (load str)
  915.       ;; -r str => (require str)
  916.       ;; -o str => (dump str)
  917.       ;; -p int => (verbose int)
  918.       ;; -m     => (set! *R4RS-macro* #t)
  919.       ;; -u     => (set! *R4RS-macro* #f)
  920.       ;; -v     => (verbose 3)
  921.       ;; -q     => (verbose 0)
  922.       ;; -i     => (set! *interactive* #t)
  923.       ;; -b     => (set! *interactive* #f)
  924.       ;; -s     => set argv, don't execute first one
  925.       ;; -no-init-file => don't load init file
  926.       ;; --no-init-file => don't load init file
  927.       ;; --help => print and exit
  928.       ;; --version => print and exit
  929.       ;; --     => last option
  930.  
  931.       (let loop ((option (getopt-- argc *argv* opts)))
  932.     (case option
  933.       ((#\a)
  934.        (cond ((> *optind* 3)
  935.           (usage "scm: option `-" getopt:opt "' must be first" #f))
  936.          ((or (not (exact? (string->number *optarg*)))
  937.               (not (<= 1 (string->number *optarg*) 10000)))
  938.           ;;    This size limit should match scm.c ^^
  939.           (usage "scm: option `-" getopt:opt
  940.              (string-append *optarg* "' unreasonable") #f))))
  941.       ((#\e #\c) (do-string-arg))    ;sh-like
  942.       ((#\f #\l) (do-load *optarg*)) ;(set-car! *argv* *optarg*)
  943.       ((#\d) (require 'database-utilities)
  944.          (open-database *optarg*))
  945.       ((#\o) (require 'dump)
  946.          (if (< *optind* (length *argv*))
  947.              (dump *optarg* #t)
  948.              (dump *optarg*)))
  949.       ((#\r) (do-thunk (lambda ()
  950.                  (if (and (= 1 (string-length *optarg*))
  951.                       (char-numeric? (string-ref *optarg* 0)))
  952.                  (case (string-ref *optarg* 0)
  953.                    ((#\2) (require 'rev3-procedures)
  954.                       (require 'rev2-procedures))
  955.                    ((#\3) (require 'rev3-procedures))
  956.                    ((#\4) (require 'rev4-optional-procedures))
  957.                    ((#\5) (require 'values)
  958.                       (require 'macro)
  959.                       (require 'eval)
  960.                       (set! *R4RS-macro* #t))
  961.                    (else (require (string->symbol *optarg*))))
  962.                  (require (string->symbol *optarg*))))))
  963.       ((#\p) (verbose (string->number *optarg*)))
  964.       ((#\q) (verbose 0))
  965.       ((#\v) (verbose 3))
  966.       ((#\i) (set! *interactive* #t) ;sh-like
  967.          (verbose (max 2 (verbose))))
  968.       ((#\b) (set! didsomething #t)
  969.          (set! *interactive* #f))
  970.       ((#\s) (set! moreopts #f)    ;sh-like
  971.          (set! didsomething #t)
  972.          (set! *interactive* #t))
  973.       ((#\m) (set! *R4RS-macro* #t))
  974.       ((#\u) (set! *R4RS-macro* #f))
  975.       ((#\n) (if (not (string=? "o-init-file" *optarg*))
  976.              (usage "scm: unrecognized option `-n" *optarg* "'" #f)))
  977.       ((#\:) (usage "scm: option `-" getopt:opt "' requires an argument" #f))
  978.       ((#\?) (usage "scm: unrecognized option `-" getopt:opt "'" #f))
  979.       ((#f) (set! moreopts #f)    ;sh-like
  980.         (cond ((and (< *optind* (length *argv*))
  981.                 (string=? "-" (list-ref *argv* *optind*)))
  982.                (set! *optind* (+ 1 *optind*)))))
  983.       (else
  984.        (or (cond ((not (string? option)) #f)
  985.              ((string-ci=? "no-init-file" option))
  986.              ((string-ci=? "version" option)
  987.               (display
  988.                (string-append exe-name " "
  989.                       (scheme-implementation-version)
  990.                       "
  991. Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
  992. "
  993.                       up-name
  994.                       " may be distributed under the terms of"
  995.                       " the GNU General Public Licence;
  996. certain other uses are permitted as well."
  997.                       " For details, see the file `COPYING',
  998. which is included in the "
  999.                       up-name " distribution.
  1000. There is no warranty, to the extent permitted by law.
  1001. "
  1002.                       ))
  1003.               (cond ((execpath) =>
  1004.                  (lambda (path)
  1005.                    (display " This executable was loaded from ")
  1006.                    (write path)
  1007.                    (newline))))
  1008.               (quit #t))
  1009.              ((string-ci=? "help" option)
  1010.               (usage "This is "
  1011.                  up-name
  1012.                  ", a Scheme interpreter."
  1013.                  (let ((sihp (scheme-implementation-home-page)))
  1014.                    (if sihp
  1015.                    (string-append "Latest info: " sihp "
  1016. ")
  1017.                    "")))
  1018.               (quit #t))
  1019.              (else #f))
  1020.            (usage "scm: unknown option `--" option "'" #f))))
  1021.  
  1022.     (cond ((and moreopts (< *optind* (length *argv*)))
  1023.            (loop (getopt-- argc *argv* opts)))
  1024.           ((< *optind* (length *argv*)) ;No more opts
  1025.            (set! *argv* (list-tail *argv* *optind*))
  1026.            (set! *optind* 1)
  1027.            (cond ((and (not didsomething) *script*)
  1028.               (do-load *script*)
  1029.               (set! *optind* (+ 1 *optind*))))
  1030.            (cond ((and (> (verbose) 2)
  1031.                (not (= (+ -1 *optind*) (length *argv*))))
  1032.               (display "scm: extra command arguments unused:"
  1033.                    (current-error-port))
  1034.               (for-each (lambda (x) (display (string-append " " x)
  1035.                              (current-error-port)))
  1036.                 (list-tail *argv* (+ -1 *optind*)))
  1037.               (newline (current-error-port)))))
  1038.           ((and (not didsomething) (= *optind* (length *argv*)))
  1039.            (set! *interactive* #t)))))
  1040.  
  1041.     (cond ((not *interactive*) (quit))
  1042.       ((and *R4RS-macro* (not (provided? 'macro)))
  1043.        (require 'repl)
  1044.        (require 'macro)
  1045.        (let* ((oquit quit))
  1046.          (set! quit (lambda () (repl:quit)))
  1047.          (set! exit quit)
  1048.          (repl:top-level macro:eval)
  1049.          (oquit))))
  1050.     ;;otherwise, fall into natural SCM repl.
  1051.     )
  1052.    (else
  1053.     (begin (errno 0)
  1054.        (set! *interactive* #t)
  1055.        (for-each load (cdr (program-arguments)))))))
  1056.